home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / smaltalk / manchest.lha / MANCHESTER / manchester / 2.2 / structure-copying.st < prev    next >
Text File  |  1993-07-24  |  18KB  |  619 lines

  1. "    NAME        structure-copying
  2.     AUTHOR        neild@cs.man.ac.uk
  3.     FUNCTION see StructureInputTable.2.3fix 
  4.     ST-VERSIONS    
  5.     PREREQUISITES     
  6.     CONFLICTS    
  7.     DISTRIBUTION      world
  8.     VERSION        1.1
  9.     DATE    22 Jan 1989
  10. SUMMARY    structure-copying
  11.      For moving Smalltalk structures between
  12.   images. This version does not work properly with 2.3 images.
  13.   To get these working file this in then file in
  14.   StructureInputTable.2.3fix.st.  Neil Dyer
  15. "!
  16. 'From Smalltalk-80, Version 2.2 of July 4, 1987 on 23 August 1988 at 5:27:06 pm'!
  17.  
  18.  
  19.  
  20. !ArrayedCollection methodsFor: 'structure copying'!
  21.  
  22. readStructureFrom: aStream structureTable: structureTable
  23.     "Read my innards from aStream. Reads in binary format if possible."
  24.  
  25.     (self class isBits and: [aStream isFileStream])
  26.         ifTrue:
  27.             [aStream binary; next: self basicSize into: self; text; skip: 3]
  28.         ifFalse:
  29.             [super readStructureFrom: aStream structureTable: structureTable]!
  30.  
  31. storeDefinitionOn: aStream structureTable: structureTable
  32.     "Stores the contents of an object. Stores in binary format if possible."
  33.  
  34.     (self class isBits and: [aStream isFileStream])
  35.         ifTrue:
  36.             [self basicSize printOn: aStream.
  37.             aStream space; binary; nextPutAll: self; text; space]
  38.         ifFalse:
  39.             [super storeDefinitionOn: aStream structureTable: structureTable]! !
  40.  
  41.  
  42.  
  43. !Boolean methodsFor: 'structure copying'!
  44.  
  45. isUniqueValue
  46.     ^true! !
  47.  
  48.  
  49.  
  50. !Character methodsFor: 'structure copying'!
  51.  
  52. storeStructureOn: aStream structureTable: structureTable
  53.     "Stores the definition of a SmallInteger aStream. This is just its
  54.      printString.
  55.      This scheme is closely based upon Steve Vegdahl's work presented in
  56.      Moving Structures between Smalltalk Images, OOPSLA '86"
  57.  
  58.     structureTable putIdOf: self on: aStream ifNew: [self printOn: aStream]! !
  59.  
  60.  
  61. !Float methodsFor: 'structure copying'!
  62.  
  63. storeStructureOn: aStream structureTable: structureTable 
  64.     "Stores the definition of a Float on aStream. This is just its  printString. 
  65.      This scheme is closely based upon Steve Vegdahl's work presented in 
  66.      Moving Structures between Smalltalk Images, OOPSLA '86"
  67.  
  68.     structureTable
  69.         putIdOf: self
  70.         on: aStream
  71.         ifNew: 
  72.             [aStream nextPut: $F.
  73.             self printOn: aStream]! !
  74.  
  75.  
  76.  
  77. !Object methodsFor: 'As yet unclassified'!
  78.  
  79. storeStructure
  80.     "Writes a description of the receiver into a file, in a way that allows
  81.      the object's structure to be reconstructed from the file's contents.
  82.      Returns the file's name"
  83.  
  84.     | fileName file |
  85.     fileName _ (FileDirectory named: '')
  86.                     requestFileName: 'Structure file name?'
  87.                     default: (self class name, '.', self asOop printString, '.structure')
  88.                     version: #any
  89.                     ifFail: [].
  90.     ^fileName ~~ nil
  91.         ifTrue: 
  92.             [
  93.             file _  FileStream fileNamed: (fileName ).
  94.             Cursor write showWhile: [self storeStructureOn: file].
  95.             file close.
  96.             fileName]! !
  97.  
  98.  
  99.  
  100. !Object methodsFor: 'public structure copying'!
  101.  
  102. storeStructureOn: aStream
  103.     "Writes a description of the receiver onto aStream, in a way that allows
  104.      the object's structure to be reconstructed from the stream's contents"
  105.  
  106.     StructureOutputTable storeStructureOf: self on: aStream! !
  107.  
  108.  
  109.  
  110. !Object methodsFor: 'structure copying'!
  111.  
  112. basicDependents 
  113.     "Answer an OrderedCollection of the objects that are dependent on the
  114.     receiver, or nil if none. This is for faster dependency access in structure
  115.     copying"
  116.  
  117.     ^DependentsFields at: self ifAbsent: []!
  118.  
  119. globalExpression
  120.     "If I am a 'global', i.e. am known on another system (e.g. Form black), return an
  121.     expression naming me in a string. Return nil if none"
  122.  
  123.     ^nil!
  124.  
  125. isUniqueValue
  126.     ^false!
  127.  
  128. readStructureFrom: aStream structureTable: structureTable
  129.     "Read my innards from aStream"
  130.  
  131.     | index |
  132.     1 to: self basicSize do: [:i|
  133.         self basicAt: i put: structureTable nextObject].
  134.     index _ 0.
  135.     [aStream peek ~~ $)]
  136.         whileTrue:
  137.             [self instVarAt: (index _ index + 1) put: structureTable nextObject].
  138.     aStream skip: 2!
  139.  
  140. storeDefinitionOn: aStream structureTable: structureTable
  141.     "Stores the contents of an object. First the number of variable fields or -
  142.      if none, then the object's instance variables, followed by its indexed variables."
  143.  
  144.     self class isVariable
  145.         ifTrue:
  146.             [self basicSize printOn: aStream.
  147.             1 to: self basicSize do: [:i|
  148.                 aStream space.
  149.                 (self basicAt: i)
  150.                     storeStructureOn: aStream
  151.                     structureTable: structureTable]]
  152.         ifFalse: [aStream nextPut: $-].
  153.     1 to: self class instSize do: [:i|
  154.         aStream space.
  155.         (self instVarAt: i) storeStructureOn: aStream structureTable: structureTable].
  156.     aStream space!
  157.  
  158. storeStructureOn: aStream structureTable: structureTable
  159.     "Stores the definition of an object onto aStream, given that the objects
  160.      in structureTable have already been seen. This method is rarely overridden.
  161.      The object's id number is written out followed by a letter identifying its form
  162.      of definition and its class name, followed by a pair of parentheses enclosing
  163.      its definition.
  164.      This scheme is closely based upon Steve Vegdahl's work presented in
  165.      Moving Structures between Smalltalk Images, OOPSLA '86"
  166.  
  167.     structureTable
  168.         putIdOf: self
  169.         on: aStream
  170.         ifNew: [
  171.             self isUniqueValue
  172.                 ifTrue: [aStream nextPut: $U; nextPutAll: self class name.
  173.                         ^self].
  174.             structureTable if: self isGlobal: [:expr|
  175.                     aStream nextPutAll: 'G<'; nextPutAll: expr; nextPut: $>.
  176.                     ^self].
  177.             aStream nextPut: $C; nextPutAll: self class name; nextPut: $(.
  178.             self storeDefinitionOn: aStream structureTable: structureTable.
  179.             aStream nextPut: $)]! !
  180.  
  181.  
  182.  
  183. !Set methodsFor: 'structure copying'!
  184.  
  185. readStructureFrom: aStream structureTable: structureTable
  186.     super readStructureFrom: aStream structureTable: structureTable.
  187.     self rehash! !
  188.  
  189.  
  190.  
  191. !SmallInteger methodsFor: 'structure copying'!
  192.  
  193. storeStructureOn: aStream structureTable: structureTable
  194.     "Stores the definition of a SmallInteger aStream. This is just its
  195.      printString.
  196.      This scheme is closely based upon Steve Vegdahl's work presented in
  197.      Moving Structures between Smalltalk Images, OOPSLA '86"
  198.  
  199.     aStream nextPut: $0.
  200.     self printOn: aStream! !
  201.  
  202.  
  203.  
  204. !String methodsFor: 'structure copying'!
  205.  
  206. storeStructureOn: aStream structureTable: structureTable
  207.     "Stores the definition of a String onto aStream.
  208.      An extra space is appended to stream to fix a problem with String>>readFrom:.
  209.      This scheme is closely based upon Steve Vegdahl's work presented in
  210.      Moving Structures between Smalltalk Images, OOPSLA '86"
  211.  
  212.     structureTable
  213.         putIdOf: self
  214.         on: aStream
  215.         ifNew: [self storeOn: aStream]! !
  216.  
  217. IdentityDictionary variableSubclass: #StructureInputTable
  218.     instanceVariableNames: 'stream currentId typeTable '
  219.     classVariableNames: 'TypeTable '
  220.     poolDictionaries: ''
  221.     category: 'System-Support'!
  222. StructureInputTable comment:
  223. 'StructureInputTable reads from a stream containing a structure produced by Object>storeStructure:on:.
  224.  
  225. The syntax is:
  226.  
  227.     <Structure>            :-        <IntegerDefinition> | <ObjectId> <ObjectDefinition>
  228.  
  229.     <IntegerDefinition>    :-        0 <integer>
  230.  
  231.     <ObjectId>                :-        <integer>
  232.  
  233.     <ObjectDefinition>    :-        G < <expression> > |
  234.                                     C <ClassName> <ObjectStructure> |
  235.                                     F <float> |
  236.                                     $ <character> |
  237.                                     # '' <symbol> '' |
  238.                                     '' <string> ''
  239.  
  240.     <ObjectStructure>    :-        ( <Size> <Contents> )
  241.  
  242.     <Size>                    :-        - | <number>
  243.  
  244.     <Contents>            :-        <ObjectId> <ObjectReference> <Contents> |
  245.                                     <>
  246.  
  247.     <ObjectReference>    :-        <ObjectDefinition> |
  248.                                     <>'!
  249.  
  250.  
  251. !StructureInputTable methodsFor: 'initialize-release'!
  252.  
  253. initialize
  254.     "The typeTable is kept in an instance variable to facilitate subclassing"
  255.     typeTable _ TypeTable! !
  256.  
  257. !StructureInputTable methodsFor: 'public access'!
  258.  
  259. readFrom: aStream
  260.     | object |
  261.     stream _ aStream.
  262.     object _ self nextObject.
  263.     self readDependencies.
  264.     ^object! !
  265.  
  266. !StructureInputTable methodsFor: 'structure reading'!
  267.  
  268. readCharacter
  269.     | character |
  270.     stream next.
  271.     character _ stream next.
  272.     stream next ~= $  ifTrue: [self syntaxError].
  273.     self at: currentId put: character.
  274.     ^character!
  275.  
  276. readFloat
  277.     | float |
  278.     stream next.
  279.     float _ self at: currentId put: (Float readFrom: stream).
  280.     stream next ~= $  ifTrue: [self syntaxError].
  281.     ^float!
  282.  
  283. readGlobal
  284.     | global |
  285.     stream next; next.
  286.     global _ self at: currentId put: (Compiler evaluate: self globalExpression).
  287.     stream next ~= $  ifTrue: [self syntaxError].
  288.     ^global!
  289.  
  290. readString
  291.     ^self at: currentId put: (String readFrom: stream)!
  292.  
  293. readSymbol
  294.     stream next.
  295.     ^self at: currentId put: (String readFrom: stream) asSymbol!
  296.  
  297. readUniqueValueDefinition
  298.     stream next.
  299.     ^self at: currentId put: (Smalltalk at: (stream upTo: $ ) asSymbol) someInstance! !
  300.  
  301. !StructureInputTable methodsFor: 'As yet unclassified'!
  302.  
  303. readClassAndDefinition
  304.     | obj class varCount |
  305.     Cursor execute showWhile: [
  306.         stream next.
  307.         class _ Smalltalk at: (stream upTo: $() asSymbol.
  308.         obj _ (stream peek = $-
  309.                     ifTrue: [stream skip: 1. class basicNew]
  310.                     ifFalse: [varCount _ Integer readFrom: stream radix: 10.
  311.                         varCount == 0 ifTrue: [class basicNew]
  312.                         ifFalse: [class basicNew: varCount]]).
  313.         stream skip: 1.
  314.         self at: currentId put: obj].
  315.     obj readStructureFrom: stream structureTable: self.
  316.     ^obj!
  317.  
  318. readDependencies
  319.     | obj |
  320.     "format: $D <objid> $( [ $  <depId> ]* $) "
  321.     [stream peek == $D]
  322.         whileTrue: [
  323.             stream skip: 1. "skip $D"
  324.             obj _ self at: (Integer readFrom: stream).
  325.             stream skip: 1. "skip ( "
  326.             [stream next ~~ $)]
  327.                 whileTrue: [
  328.                     obj addDependent: (self at: (Integer readFrom: stream))]]! !
  329.  
  330. !StructureInputTable methodsFor: 'adding'!
  331.  
  332. grow
  333.     "Must copy instance variables when growing"
  334.     | theStream theId theTypeTable |
  335.     theStream _ stream. theId _ currentId. theTypeTable _ typeTable.
  336.     super grow.    "does the grow & become"
  337.     stream _ theStream. currentId _ theId. typeTable _ theTypeTable! !
  338.  
  339. !StructureInputTable methodsFor: 'private'!
  340.  
  341. findKeyOrNil: key
  342.     "My keys are integers. Use their values for their hash, rather than their oop."
  343.     | index length probe pass |
  344.     length _ self basicSize.
  345.     pass _ 1.
  346.     index _ key \\ length + 1.
  347.     [(probe _ self basicAt: index) == nil or: [probe == key]]
  348.         whileFalse: [(index _ index + 1) > length
  349.                 ifTrue: 
  350.                     [index _ 1.
  351.                     pass _ pass + 1.
  352.                     pass > 2 ifTrue: [^self grow findKeyOrNil: key]]].
  353.     ^index!
  354.  
  355. globalExpression
  356.     | aStream char |
  357.     aStream _ WriteStream on: (String new: 16).
  358.     [(char _ stream next) ~~ $>]
  359.         whileTrue:
  360.             [aStream nextPut: char].
  361.     ^aStream contents!
  362.  
  363. nextObject
  364.     "Read the Object Id then the definition"
  365.     ^self perform: (typeTable at: stream peek asciiValue)!
  366.  
  367. readId
  368.     "This is called from nextObject. Read the Object ID then the definition."
  369.     | char |
  370.     currentId _ Integer readFrom: stream radix: 10.
  371.     ^((char _ stream peek) == $  or: [char == $)])
  372.         ifTrue: [stream skip: 1. self at: currentId]
  373.         ifFalse: [self perform: (typeTable at: char asciiValue)]!
  374.  
  375. readInteger
  376.     "This is called from nextObject. There is no Object Id. Read the definition."
  377.     | integer |
  378.     stream next.
  379.     integer _ Integer readFrom: stream.
  380.     stream next ~= $  ifTrue: [self syntaxError].
  381.     ^integer!
  382.  
  383. rehash
  384.     "Must copy instance variables when rehashing"
  385.     | theStream theId theTypeTable |
  386.     theStream _ stream. theId _ currentId. theTypeTable _ typeTable.
  387.     super rehash.    "does the rehash & become"
  388.     stream _ theStream. currentId _ theId. typeTable _ theTypeTable!
  389.  
  390. syntaxError
  391.     self error: 'syntax error: space expected'! !
  392. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  393.  
  394. StructureInputTable class
  395.     instanceVariableNames: ''!
  396.  
  397.  
  398. !StructureInputTable class methodsFor: 'class initialization'!
  399.  
  400. initialize
  401.     "StructureInputTable initialize"
  402.  
  403.     TypeTable _ Array new: 256.
  404.  
  405.     "Token start characters"
  406.     TypeTable at: $0 asciiValue put: #readInteger.
  407.     $1 asciiValue to: $9 asciiValue do: [:ascii| TypeTable at: ascii put: #readId].
  408.  
  409.     "Definition type start characters"
  410.     TypeTable
  411.         at: $G asciiValue put: #readGlobal;
  412.         at: $U asciiValue put: #readUniqueValueDefinition;
  413.         at: $C asciiValue put: #readClassAndDefinition;
  414.         at: $F asciiValue put: #readFloat;
  415.         at: $$ asciiValue put: #readCharacter;
  416.         at: $# asciiValue put: #readSymbol;
  417.         at: $' asciiValue put: #readString! !
  418.  
  419. !StructureInputTable class methodsFor: 'instance creation'!
  420.  
  421. new: anInteger
  422.     ^(super new: anInteger) initialize! !
  423.  
  424. !StructureInputTable class methodsFor: 'structure reading'!
  425.  
  426. readFrom: streamOrFileName
  427.  
  428.     "Reads an object's structure from the stream streamOrFileName
  429.      or the file named streamOrFileName"
  430.  
  431.     (streamOrFileName isKindOf: String)
  432.         ifTrue:
  433.             [^Cursor read showWhile: [(self new: 1024) readFrom: (FileStream fileNamed: streamOrFileName)]].
  434.     ^(self new: 1024) readFrom: streamOrFileName! !
  435.  
  436. StructureInputTable initialize!
  437.  
  438. IdentityDictionary variableSubclass: #StructureOutputTable
  439.     instanceVariableNames: 'idCount idOfNil globalDictionaries globals '
  440.     classVariableNames: 'GlobalDictionaries Globals '
  441.     poolDictionaries: ''
  442.     category: 'System-Support'!
  443.  
  444.  
  445. !StructureOutputTable methodsFor: 'initialize-release'!
  446.  
  447. initialize
  448.     "You should change this method to add whatever objects you consider
  449.      constant across systems, and remove any objects you don't consider
  450.      constant. Also, you can implement globalExpression for specific classes."
  451.  
  452.     globals _ Globals.
  453.     globalDictionaries _ GlobalDictionaries.
  454.     idCount _ 0! !
  455.  
  456. !StructureOutputTable methodsFor: 'As yet unclassified'!
  457.  
  458. appendDependenciesTo: aStream 
  459.     |dependents noDependents depId|
  460.     "Add dependency information to aStream. 
  461.      The structure has been stored on aStream, thus the table 
  462.     contains all objects 
  463.      other than SmallIntegers contained in the structure. We add 
  464.     only the dependencies 
  465.      between objects in the structure and we miss dependencies 
  466.     of SmallIntegers"
  467.  
  468.     self keysDo: [:obj |
  469.         (dependents _ obj basicDependents) ~~ nil
  470.             ifTrue: [
  471.                 noDependents _ true.
  472.                 dependents do:  [:dep |
  473.                     (depId _ self at: dep ifAbsent: []) ~~ nil
  474.                         ifTrue: [
  475.                             noDependents
  476.                                 ifTrue: [
  477.                                     aStream space; nextPut: $D.
  478.                                     (self at: obj) printOn: aStream base: 10.
  479.                                     aStream nextPut: $(.
  480.                                     noDependents _ false].
  481.                             aStream space.
  482.                             depId printOn: aStream base: 10]].
  483.                 noDependents ifFalse: [aStream nextPut: $)]]]!
  484.  
  485. putIdOf: anObject on: aStream ifNew: aBlock
  486.  
  487.     | cursor |
  488.     (self at: anObject ifAbsent: [
  489.         cursor _ Sensor currentCursor.
  490.         Cursor execute show.
  491.  
  492.         anObject == nil
  493.             ifTrue: [
  494.                 idOfNil == nil
  495.                     ifTrue: [
  496.                         (idOfNil _ (idCount _ idCount + 1)) printOn: aStream base: 10.
  497.                         cursor show.
  498.                         ^aBlock value].
  499.                 cursor show.
  500.                 idOfNil]
  501.             ifFalse: [
  502.                 (self at: anObject put: (idCount _ idCount + 1)) printOn: aStream base: 10.
  503.                 cursor show.
  504.                 ^aBlock value]])
  505.         printOn: aStream! !
  506.  
  507. !StructureOutputTable methodsFor: 'testing'!
  508.  
  509. if: anObject isGlobal: aBlock
  510.  
  511.     | globalExpression |
  512.  
  513.     (globalExpression _ anObject globalExpression) ~~ nil
  514.         ifTrue: [^aBlock value: globalExpression].
  515.  
  516.     (globalExpression _ globals at: anObject ifAbsent: []) ~~ nil
  517.         ifTrue: [^aBlock value: globalExpression].
  518.  
  519.     globalDictionaries do: [:dict|
  520.         dict associationsDo: [:assoc|
  521.             assoc value == anObject
  522.                 ifTrue: [^aBlock value: (Smalltalk keyAtValue: dict), ' at: ', assoc key storeString]]]! !
  523.  
  524. !StructureOutputTable methodsFor: 'adding'!
  525.  
  526. grow
  527.     "Must copy instance variables when growing"
  528.     | theIdCount theIdOfNil theGlobalDictionaries theGlobals |
  529.     theIdCount _ idCount. theIdOfNil _ idOfNil. theGlobals _ globals.
  530.     theGlobalDictionaries _ globalDictionaries.
  531.     super grow.    "does the grow & become"
  532.     idCount _ theIdCount. idOfNil _ theIdOfNil. globals _ theGlobals.
  533.     globalDictionaries _ theGlobalDictionaries! !
  534.  
  535. !StructureOutputTable methodsFor: 'private'!
  536.  
  537. rehash
  538.     "Must copy instance variables when rehashing"
  539.     | theIdCount theIdOfNil theGlobalDictionaries theGlobals |
  540.     theIdCount _ idCount. theIdOfNil _ idOfNil. theGlobals _ globals.
  541.     theGlobalDictionaries _ globalDictionaries.
  542.     super rehash.    "does the rehash & become"
  543.     idCount _ theIdCount. idOfNil _ theIdOfNil. globals _ theGlobals.
  544.     globalDictionaries _ theGlobalDictionaries! !
  545. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  546.  
  547. StructureOutputTable class
  548.     instanceVariableNames: ''!
  549.  
  550.  
  551. !StructureOutputTable class methodsFor: 'As yet unclassified'!
  552.  
  553. initialize
  554.     |object|
  555.     "Collect the objects considered `global' i.e. shared between systems.
  556.      You should change this method to add whatever objects you consider
  557.      constant across systems, and remove any objects you don't consider
  558.      constant. Also, look at the instance method initialize for further customization."
  559.  
  560.     "StructureOutputTable initialize"
  561.  
  562.     Globals _ IdentityDictionary new: 64.
  563.     GlobalDictionaries _ IdentityDictionary new: 16.
  564.  
  565.     "Provisionally assume all objects in Smalltalk except processes, and all objects
  566.      in all dictionaries in Smalltalk except Undeclared (typically pools) are `global'"
  567.     Smalltalk associationsDo: [:assoc|
  568.         (((object _ assoc value) isKindOf: Behavior) or: [object isKindOf: Process])
  569.             ifFalse:
  570.                 [Globals at: object put: assoc key.
  571.                 (object ~~ Smalltalk and: [(object isKindOf: Dictionary) and: [object ~~ Undeclared]])
  572.                     ifTrue:
  573.                         [GlobalDictionaries add: assoc]]].
  574.  
  575.     "Provisionally assume the default fonts & Form masks are `global'"
  576.     1 to: TextStyle default fontArray size do: [:fontIndex|
  577.         Globals
  578.             at: (TextStyle default fontAt: fontIndex)
  579.             put: 'TextStyle default fontAt: ', fontIndex printString].
  580.  
  581.     #( white veryLightGray lightGray gray darkGray black ) do: [:maskName|
  582.         Globals
  583.             at: (Form perform: maskName)
  584.             put: 'Form ', maskName]! !
  585.  
  586. !StructureOutputTable class methodsFor: 'structure copying'!
  587.  
  588. storeStructureOf: anObject on: aStream
  589.     | table |
  590.     table _ (self new: 1024) initialize.
  591.     anObject storeStructureOn: aStream structureTable: table.
  592.     table appendDependenciesTo: aStream! !
  593.  
  594. StructureOutputTable initialize!
  595.  
  596.  
  597.  
  598. !Symbol methodsFor: 'structure copying'!
  599.  
  600. storeStructureOn: aStream structureTable: structureTable
  601.     "Stores the definition of a Symbol onto aStream.
  602.      An extra space is appended to stream to fix a problem with String>>readFrom:.
  603.      This scheme is closely based upon Steve Vegdahl's work presented in
  604.      Moving Structures between Smalltalk Images, OOPSLA '86"
  605.  
  606.     structureTable
  607.         putIdOf: self
  608.         on: aStream
  609.         ifNew: [aStream nextPut: $#. super storeOn: aStream]! !
  610.  
  611.  
  612.  
  613. !UndefinedObject methodsFor: 'structure copying'!
  614.  
  615. isUniqueValue
  616.     ^true! !
  617.  
  618.  
  619.